#include <iostream>
#include <string>
#include <cstring>
#include <functional>

#include "Thread.hpp"

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

void SendMessage(int sockfd,  std::string ip, uint16_t port, std::string thread_name)
{
    struct sockaddr_in sever;
    memset(&sever, 0, sizeof(sever));
    sever.sin_family = AF_INET;
    sever.sin_port = htons(port);
    sever.sin_addr.s_addr = inet_addr(ip.c_str());
    while(1)
    {
        std::string line;
        std::cout<< "Please Enter" <<std::endl;
        std::getline(std::cin, line);

        int n = sendto(sockfd, line.c_str(), line.size(), 0, (struct sockaddr*)&sever, sizeof(sever));
        if(n <= 0) break;
    }
}
void ReceiveMessage(int sockfd, std::string thread_name)
{
    while(1)
    {
        struct sockaddr_in tmp;
        socklen_t len = sizeof(tmp);
        char buf[1024];

        int num = recvfrom(sockfd, buf, sizeof(buf)-1, 0, (struct sockaddr*)&tmp, &len);
        if(num > 0)
        {
            buf[num] = 0;
            std::cerr << buf <<std::endl;
        }
        else
        {
            std::cerr << "receive error" << std::endl;
            break;
        }
    }
}
//./client 服务器的IP 服务端的端口号
int main(int argc, char* argv[])
{
    if(argc != 3)
    {
        std::cout<< argv[0] << "serve-ip serve-port" <<std::endl;
        exit(0);
    }
    //创建socket文件
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if(sockfd < 0)
    {
        std::cout<< "socket creat error" <<std::endl;
        exit(1);
    }
    
    std::string ip = argv[1];
    uint16_t port = std::stoi(argv[2]);
    //之前写的发消息收消息是在一个线程执行的，代码逻辑是每发完消息后，再从socket文件中收消息
    //但是我们向要的客户端的样子是，无论发不发消息都能从socket文件中收消息，所以客户端同样需要多线程
    //一个线程发消息，一个线程从网络中接收消息，发的消息显示在一个终端文件中，接收的消息显示在另一个终端文件中
    //创建两个线程，一个线程发消息，一个线程收消息
    Thread receive_thread("receive-thread", std::bind(&SendMessage, sockfd, ip, port, std::placeholders::_1));
    Thread send_thread("send-thread", std::bind(&ReceiveMessage, sockfd, std::placeholders::_1));
    //启动两个线程
    receive_thread.Start();
    send_thread.Start();
    receive_thread.join();
    send_thread.join();
    //关闭socket文件
    close(sockfd);
   
    return 0;
}


